home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / disk / misc / Mtools207.lha / Mtools-2.0.7 / src / buf_write.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-27  |  3.5 KB  |  167 lines

  1. /*
  2.  * Do full cylinder buffered writes to slow devices.  Uses a simple
  3.  * buffered read/delayed write algorithm
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "msdos.h"
  8. #include "amiga_devices.h"
  9.  
  10. extern struct device_data * ddata;
  11.  
  12. extern int fd, disk_size, disk_dirty, dir_start, dir_len;
  13. extern int clus_size;
  14. extern long disk_offset, disk_current;
  15. extern unsigned char *disk_buf;
  16. static int read_cyl();
  17.  
  18. void
  19. disk_write(start, buf, len)
  20. long start;
  21. unsigned char *buf;
  22. int len;
  23. {
  24.     register long i;
  25.     int length;
  26.     unsigned char *buf_ptr, *disk_ptr;
  27.     char *memcpy();
  28.     void perror(), exit(), disk_flush();
  29.     long where, tail, lseek();
  30.  
  31.                     /* don't use cache? */
  32.     if (disk_size == 1) {
  33.         
  34.         where = (start * MSECTOR_SIZE) + disk_offset;
  35.         
  36.         if (ddata != 0) {
  37.             if (len != (int) device_write( ddata, (ulong) where, (ulong) len, buf) ) {
  38.                 perror("disk_write: write");
  39.                 exit(1);
  40.             }
  41.         }
  42.         else {
  43.             if (lseek(fd, where, 0) < 0) {
  44.                 perror("disk_write: lseek");
  45.                 exit(1);
  46.             }
  47.                         /* write it! */
  48.             if (write(fd, (char *) buf, (unsigned int) len) != len) {
  49.                 perror("disk_write: write");
  50.                 exit(1);
  51.             }
  52.         }
  53.         return;
  54.     }
  55.  
  56.     tail = start + (len / MSECTOR_SIZE) - 1;
  57.     for (i = start; i <= tail; i++) {
  58.                     /* a cache miss... */
  59.         if (i < disk_current || i >= disk_current + disk_size) {
  60.  
  61.             if (disk_dirty)
  62.                 disk_flush();
  63.  
  64.             disk_current = (i / disk_size) * disk_size;
  65.             /*
  66.              * If there is something on the new cylinder that
  67.              * you want to keep, you'll have to read it first
  68.              * before writing.
  69.              */
  70.             if (read_cyl(disk_current)) {
  71.                 where = (disk_current * MSECTOR_SIZE) + disk_offset;
  72.                 length = disk_size * MSECTOR_SIZE;
  73.  
  74.                 if (ddata != 0) {
  75.                     if (length != (int) device_read( ddata, (ulong) where, (ulong) length, disk_buf) ) {
  76.                         perror("disk_write: read");
  77.                         exit(1);
  78.                     }
  79.                 }
  80.                 else {
  81.                             /* move to next location */
  82.                     if (lseek(fd, where, 0) < 0) {
  83.                         perror("disk_write: lseek");
  84.                         exit(1);
  85.                     }
  86.                         /* read it! */
  87.                     if (read(fd, (char *) disk_buf, (unsigned int) length) != length) {
  88.                         perror("disk_write: read");
  89.                         exit(1);
  90.                     }
  91.                 }
  92.             }
  93.         }
  94.                     /* a cache hit ... */
  95.         buf_ptr = buf + ((i - start) * MSECTOR_SIZE);
  96.         disk_ptr = disk_buf + ((i - disk_current) * MSECTOR_SIZE);
  97.         memcpy((char *) disk_ptr, (char *) buf_ptr, MSECTOR_SIZE);
  98.         disk_dirty = 1;
  99.     }
  100.     return;
  101. }
  102.  
  103. /*
  104.  * Flush a dirty buffer to disk.  Resets disk_dirty to zero.
  105.  * All errors are fatal.
  106.  */
  107.  
  108. void
  109. disk_flush()
  110. {
  111.     int len;
  112.     long where, lseek();
  113.     void perror(), exit();
  114.  
  115.     if (fd < 0 || disk_current < 0L || !disk_dirty)
  116.         return;
  117.  
  118.     where = (disk_current * MSECTOR_SIZE) + disk_offset;
  119.     
  120.     len = disk_size * MSECTOR_SIZE;
  121.     if (ddata != 0) {
  122.         if (len != (int) device_write( ddata, (ulong) where, (ulong) len, disk_buf) ) {
  123.             perror("disk_flush: write");
  124.             exit(1);
  125.         }
  126.     }
  127.     else {
  128.         if (lseek(fd, where, 0) < 0) {
  129.             perror("disk_flush: lseek");
  130.             exit(1);
  131.         }
  132.                         /* write it! */
  133.         if (write(fd, (char *) disk_buf, (unsigned int) len) != len) {
  134.             perror("disk_flush: write");
  135.             exit(1);
  136.         }
  137.     }
  138.     disk_dirty = 0;
  139.     return;
  140. }
  141.  
  142. /*
  143.  * Determine if the cylinder has some useful information on it.  Returns a 1
  144.  * if it needs to be read.
  145.  */
  146.  
  147. static int
  148. read_cyl(sector)
  149. long sector;
  150. {
  151.     register unsigned int i;
  152.     unsigned int start, end, fat_decode();
  153.  
  154.     if (!sector)
  155.         return(1);
  156.  
  157.     start = ((sector - dir_start - dir_len) / clus_size) + 2;
  158.     end = ((sector + disk_size - dir_start - dir_len) / clus_size) + 2;
  159.  
  160.     for (i = start; i < end; i++) {
  161.                     /* if fat_decode returns non-zero */
  162.         if (fat_decode(i))
  163.             return(1);
  164.     }
  165.     return(0);
  166. }
  167.